package auctionhausen

import grails.converters.JSON

import java.util.timer.*

class ListingService {

	private final static String LISTING_EXPIRATION_QUEUE_NAME = "auctionhausen.ListingCompletionQueue"
	private static final String WINNER_CONFIRMATION_EMAIL_SUBJECT = "Auction Hausen - Listing Winner - "

	def jmsService
	def emailService

	def getListing(id) {
		return Listing.get(id)
	}

	Boolean isListingExpired(Listing listing) {
		return listing.expired
	}

	def createListing(def params) {
		def listingInstance = new Listing(params)
		listingInstance.expired = false
		listingInstance.save(failOnError:true)
		return listingInstance
	}

	def getCurrentMinimumBidForListing(listingID) {
		def getMinimumBidResponse = [expired: false, value: 0]
		def listing = Listing.get(listingID);
		if (listing && isListingExpired(listing)) {
			getMinimumBidResponse.expired = true
		} else if (listing && listing?.bids?.size()) {
			def queryParams = [
						sort : "amount",
						order : "desc",
						max : 1]
			def bids = Bid.findAllByListing(listing, queryParams)
			if (!bids.isEmpty()) {
				getMinimumBidResponse.value = bids[0].amount + Bid.MINIMUM_BID_DIFFERENCE
			}
		}
		else {
			getMinimumBidResponse.value = listing.startingPrice + Bid.MINIMUM_BID_DIFFERENCE
		}
		return getMinimumBidResponse
	}

	private Bid getWinningBidForlisting(Listing listing) {
		def winningBid = null
		def queryParams = [
					sort : "dateCreated",
					order : "desc",
					max : 1]
		def listingBids = Bid.findAllByListing(listing, queryParams)
		if (!listingBids.isEmpty()) {
			winningBid = listingBids[0]
		}

		return winningBid
	}

	private def createWinnerConfirmationEmailSubject(Listing listing) {
		return "${WINNER_CONFIRMATION_EMAIL_SUBJECT} - ${listing.name}"
	}

	def synchronized listingExpired(Listing listing) {
		if (listing) {
			listing.expired = true;
			def winningBid = getWinningBidForlisting(
					listing)
			if (winningBid) {
				listing.winner = winningBid.bidder
			}
			listing.save(flush:true)
			publishJMSMessageForListing(listing)
			sendConfirmationEmailToWinner(listing, winningBid)
		}
	}

	private synchronized def publishJMSMessageForListing(Listing listing) {
		def listingJson = listing as JSON
		jmsService.send(queue: LISTING_EXPIRATION_QUEUE_NAME, listingJson.toString())
	}

	synchronized def sendConfirmationEmailToWinner(Listing listing, Bid winningBid) {
		if (listing.winner) {
			emailService.sendEmail(createWinningConfirmationEmail(listing, winningBid))
		}
	}

	private def createWinningConfirmationEmail(Listing listing, Bid bid) {
		return new EmailContent (
		to : listing.winner.email,
		subject : createWinnerConfirmationEmailSubject(listing),
		model : [listingInstance: listing, winningBidPrice: bid.amount],
		mailTemplateURI : "/ListingWinnerConfirmationEmail"
		)
	}
}
